/*
	Simple Software Renderer (SSRenderer)
	Copyright (C) 2007 Piotr Orzechowski <piotr.orzechowski@gmail.com>

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
*/

#include "./SSRRenderer.h"

namespace ssr
{

SSRRenderer::SSRRenderer()
{
	// No render target
	m_pTarget = NULL;
	m_pColorBuffer = NULL;
	m_pColorSurface = NULL;

	// Set error messages
	m_ErrorStack.SetErrorStrings(ERROR_STRINGS, ERROR_STRINGS_COUNT);
}

SSRRenderer::~SSRRenderer()
{
    SSR_RELEASE(m_pTarget);
}

bool SSRRenderer::SetRenderTarget(SSRRenderTarget *target)
{
	if (m_pTarget == NULL || !m_pTarget->IsLocked())
	{
	    // Release previous rendering target
	    SSR_RELEASE(m_pTarget);

		m_pTarget = target;

        m_pColorSurface = NULL;
        m_pColorBuffer = NULL;
        m_ColorBufferPitch = 0;

		return true;
	}
	else
	{
		m_ErrorStack.Push("SetRenderTarget", SSRERR_CSRT);
		return false;
	}
}

void SSRRenderer::SetViewport(u32 x, u32 y, u32 width, u32 height)
{
	m_Viewport.x = x;
	m_Viewport.y = y;
	m_Viewport.width = width;
	m_Viewport.height = height;
}

void SSRRenderer::BeginDrawing()
{
	// Make sure we've got a valid rendering target
	if (m_pTarget == NULL)
	{
		m_ErrorStack.Push("BeginDrawing", SSRERR_RTN);
		return;
	}

	m_pColorSurface = m_pTarget->GetColorSurface();
	if (m_pColorSurface == NULL)
	{
		m_ErrorStack.Push("BeginDrawing", SSRERR_CSN);
		return;
	}

	m_pColorBuffer = m_pColorSurface->GetBuffer();
	if (m_pColorBuffer == NULL)
	{
		m_ErrorStack.Push("BeginDrawing", SSRERR_CBN);
		return;
	}

	if (m_pTarget->IsLocked())
	{
		m_ErrorStack.Push("BeginDrawing", SSRERR_RTAL);
		return;
	}
	m_pTarget->Lock();

	m_ColorBufferPitch = m_pColorSurface->GetPitch();

	// Now, if we got so far we can be sure that nothing
	// bad can happen when using raster operations.
}

void SSRRenderer::EndDrawing()
{
	if (m_pTarget == NULL)
	{
		m_ErrorStack.Push("EndDrawing", SSRERR_RTN);
		return;
	}

	if (!m_pTarget->IsLocked())
	{
		m_ErrorStack.Push("EndDrawing", SSRERR_RTNL);
		return;
	}
	m_pTarget->Unlock();

	// We no longer need the pointer to the color surface and the buffer
	SSR_RELEASE(m_pColorSurface);
    m_pColorBuffer = NULL;
    m_ColorBufferPitch = 0;
}

} // namespace

